home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / apps / 21 / emacsrc / vdisplay.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-05-14  |  12.0 KB  |  434 lines

  1. /*
  2.  * The functions in this file handle redisplay. There are two halves, the
  3.  * ones that update the virtual display screen, and the ones that make the
  4.  * physical display screen the same as the virtual display screen. These
  5.  * functions use hints that are left in the windows by the commands.
  6.  *
  7.  * REVISION HISTORY:
  8.  *
  9.  * ?    Steve Wilhite, 1-Dec-85
  10.  *      - massive cleanup on code.
  11.  * prabhaker mateti, 1-1-86, ST520 changes
  12.  */
  13.  
  14. #include        "ed.h"
  15. #include    "osbind.h"
  16.  
  17. #define WFDEBUG 0                       /* Window flag debug. */
  18.  
  19.  
  20. #define VFCHG   0x0001                  /* Changed. */
  21. #define MDLIN   0x0002                  /* Mode line indicator. */
  22.  
  23. int     sgarbf  = TRUE;                 /* TRUE if screen is garbage */
  24. int     mpresf  = FALSE;                /* TRUE if message in last line */
  25. int     vtrow   = 0;                    /* Row location of SW cursor */
  26. int     vtcol   = 0;                    /* Column location of SW cursor */
  27. int     ttrow   = HUGE;                 /* Row location of HW cursor */
  28. int     ttcol   = HUGE;                 /* Column location of HW cursor */
  29.  
  30. VIDEO   **vscreen;                      /* Virtual screen. */
  31. VIDEO   **pscreen;                      /* Physical screen. */
  32.  
  33. /*
  34.  * Initialize the data structures used by the display code. The edge vectors
  35.  * used to access the screens are set up. The operating system's terminal I/O
  36.  * channel is set up. All the other things get initialized at compile time.
  37.  * The original window has "WFCHG" set, so that it will get completely
  38.  * redrawn on the first call to "update".
  39.  */
  40. vtinit()
  41. {
  42.     register int i;
  43.     register VIDEO *vp;
  44.  
  45.     vscreen = (VIDEO **) malloc(term.t_nrow*sizeof(VIDEO *));
  46.     if (vscreen == NULL)
  47.         exit(1);
  48.  
  49.     pscreen = (VIDEO **) malloc(term.t_nrow*sizeof(VIDEO *));
  50.  
  51.     if (pscreen == NULL)
  52.         exit(1);
  53.  
  54.     for (i = 0; i < term.t_nrow; ++i)
  55.         {
  56.         vp = (VIDEO *) malloc(sizeof(VIDEO)+term.t_ncol);
  57.  
  58.         if (vp == NULL)
  59.             exit(1);
  60.  
  61.         vscreen[i] = vp;
  62.         vp = (VIDEO *) malloc(sizeof(VIDEO)+term.t_ncol);
  63.  
  64.         if (vp == NULL)
  65.             exit(1);
  66.  
  67.         pscreen[i] = vp;
  68.         }
  69. }
  70.  
  71. /*
  72.  * Clean up the virtual terminal system, in anticipation for a return to the
  73.  * operating system. Move down to the last line and clear it out (the next
  74.  * system prompt will be written in the line). Shut down the channel to the
  75.  * terminal.
  76.  */
  77. vttidy()
  78. {
  79.     movecursor(term.t_nrow, 0);
  80. /*    (*term.t_eeol)();        */
  81. /*    (*term.t_close)();    */
  82.     Cconws("\033K");
  83. }
  84.  
  85. /*
  86.  * Set the virtual cursor to the specified row and column on the virtual
  87.  * screen. There is no checking for nonsense values; this might be a good
  88.  * idea during the early stages.
  89.  */
  90. vtmove(row, col)
  91. {
  92.     vtrow = row;
  93.     vtcol = col;
  94. }
  95.  
  96. /*
  97.  * Write a character to the virtual screen. The virtual row and column are
  98.  * updated. If the line is too long put a "$" in the last column. This routine
  99.  * only puts printing characters into the virtual terminal buffers. Only
  100.  * column overflow is checked.
  101.  */
  102. vtputc(c)
  103.     int c;
  104. {
  105.     register VIDEO      *vp;
  106.  
  107.     vp = vscreen[vtrow];
  108.  
  109.     if (vtcol >= term.t_ncol)
  110.         vp->v_text[term.t_ncol - 1] = '$';
  111.     else if (c == '\t')
  112.         {
  113.         do
  114.             {
  115.             vtputc(' ');
  116.             }
  117.         while ((vtcol&0x07) != 0);
  118.         }
  119.     else if (c < 0x20 || c == 0x7F)
  120.         {
  121.         vtputc('^');
  122.         vtputc(c ^ 0x40);
  123.         }
  124.     else
  125.         vp->v_text[vtcol++] = c;                
  126. }
  127.  
  128. /*
  129.  * Erase from the end of the software cursor to the end of the line on which
  130.  * the software cursor is located.
  131.  */
  132. vteeol()
  133. {
  134.     register VIDEO      *vp;
  135.  
  136.     vp = vscreen[vtrow];
  137.     while (vtcol < term.t_ncol)
  138.         vp->v_text[vtcol++] = ' ';
  139. }
  140.  
  141. /*
  142.  * Make sure that the display is right. This is a three part process. First,
  143.  * scan through all of the windows looking for dirty ones. Check the framing,
  144.  * and refresh the screen. Second, make sure that "currow" and "curcol" are
  145.  * correct for the current window. Third, make the virtual and physical
  146.  * screens the same.
  147.  */
  148. update()
  149. {
  150.     register LINE *lp;
  151.     register WINDOW *wp;
  152.     register VIDEO *vp1;
  153.     register VIDEO *vp2;
  154.     register int i;
  155.     register int j;
  156.     register int c;
  157.  
  158.     Cconws("\033q");    /* reverse video off (hack!)    */
  159.     wp = wheadp;
  160.  
  161.     while (wp != NULL)
  162.         {
  163.         /* Look at any window with update flags set on. */
  164.  
  165.         if (wp->w_flag != 0)
  166.             {
  167.             /* If not force reframe, check the framing. */
  168.  
  169.             if ((wp->w_flag & WFFORCE) == 0)
  170.                 {
  171.                 lp = wp->w_linep;
  172.  
  173.                 for (i = 0; i < wp->w_ntrows; ++i)
  174.                     {
  175.                     if (lp == wp->w_dotp)
  176.                         goto out;
  177.  
  178.                     if (lp == wp->w_bufp->b_linep)
  179.                         break;
  180.  
  181.                     lp = lforw(lp);
  182.                     }
  183.                 }
  184.  
  185.             /* Not acceptable, better compute a new value for the line at the
  186.              * top of the window. Then set the "WFHARD" flag to force full
  187.              * redraw.
  188.              */
  189.             i = wp->w_force;
  190.  
  191.             if (i > 0)
  192.                 {
  193.                 --i;
  194.  
  195.                 if (i >= wp->w_ntrows)
  196.                   i = wp->w_ntrows-1;
  197.                 }
  198.             else if (i < 0)
  199.                 {
  200.                 i += wp->w_ntrows;
  201.  
  202.                 if (i < 0)
  203.                     i = 0;
  204.                 }
  205.             else
  206.                 i = wp->w_ntrows/2;
  207.  
  208.             lp = wp->w_dotp;
  209.  
  210.             while (i != 0 && lback(lp) != wp->w_bufp->b_linep)
  211.                 {
  212.                 --i;
  213.                 lp = lback(lp);
  214.                 }
  215.  
  216.             wp->w_linep = lp;
  217.             wp->w_flag |= WFHARD;       /* Force full. */
  218.  
  219. out:
  220.             /* Try to use reduced update. Mode line update has its own special
  221.              * flag. The fast update is used if the only thing to do is within
  222.              * the line editing.
  223.              */
  224.             lp = wp->w_linep;
  225.             i = wp->w_toprow;
  226.  
  227.             if ((wp->w_flag & ~WFMODE) == WFEDIT)
  228.                 {
  229.                 while (lp != wp->w_dotp)
  230.                     {
  231.                     ++i;
  232.                     lp = lforw(lp);
  233.                     }
  234.  
  235.                 vscreen[i]->v_flag |= VFCHG;
  236.                 vtmove(i, 0);
  237.  
  238.                 for (j = 0; j < llength(lp); ++j)
  239.                     vtputc(lgetc(lp, j));
  240.  
  241.                 vteeol();
  242.                 }
  243.              else if ((wp->w_flag & (WFEDIT | WFHARD)) != 0)
  244.                 {
  245.                 while (i < wp->w_toprow+wp->w_ntrows)
  246.                     {
  247.                     vscreen[i]->v_flag |= VFCHG;
  248.                     vscreen[i]->v_flag &= ~MDLIN;
  249.                     vtmove(i, 0);
  250.  
  251.                     if (lp != wp->w_bufp->b_linep)
  252.                         {
  253.                         for (j = 0; j < llength(lp); ++j)
  254.                             vtputc(lgetc(lp, j));
  255.  
  256.                         lp = lforw(lp);
  257.                         }
  258.  
  259.                     vteeol();
  260.                     ++i;
  261.                     }
  262.                 }
  263. #if ~WFDEBUG
  264.             if ((wp->w_flag&WFMODE) != 0)
  265.                 modeline(wp);
  266.  
  267.             wp->w_flag  = 0;
  268.             wp->w_force = 0;
  269. #endif
  270.             }           
  271. #if WFDEBUG
  272.         modeline(wp);
  273.         wp->w_flag =  0;
  274.         wp->w_force = 0;
  275. #endif
  276.         wp = wp->w_wndp;
  277.         }
  278.  
  279.     /* Always recompute the row and column number of the hardware cursor. This
  280.      * is the only update for simple moves.
  281.      */
  282.     lp = curwp->w_linep;
  283.     currow = curwp->w_toprow;
  284.  
  285.     while (lp != curwp->w_dotp)
  286.         {
  287.         ++currow;
  288.         lp = lforw(lp);
  289.         }
  290.  
  291.     curcol = 0;
  292.     i = 0;
  293.  
  294.     while (i < curwp->w_doto)
  295.         {
  296.         c = lgetc(lp, i++);
  297.  
  298.         if (c == '\t')
  299.             curcol |= 0x07;
  300.         else if (c < 0x20 || c == 0x7F)
  301.             ++curcol;
  302.  
  303.         ++curcol;
  304.         }
  305.  
  306.     if (curcol >= term.t_ncol)          /* Long line. */
  307.         curcol = term.t_ncol-1;
  308.  
  309.     /* Special hacking if the screen is garbage. Clear the hardware screen,
  310.      * and update your copy to agree with it. Set all the virtual screen
  311.      * change bits, to force a full update.
  312.      */
  313.     if (sgarbf != FALSE)
  314.         {
  315.         for (i = 0; i < term.t_nrow; ++i)
  316.             {
  317.             vscreen[i]->v_flag |= VFCHG;
  318.             vp1 = pscreen[i];
  319.             for (j = 0; j < term.t_ncol; ++j)
  320.                 vp1->v_text[j] = ' ';
  321.             }
  322.  
  323.         movecursor(0, 0);               /* Erase the screen. */
  324. /*        (*term.t_eeop)();    */
  325.     Cconws("\033J");
  326.         sgarbf = FALSE;                 /* Erase-page clears */
  327.         mpresf = FALSE;                 /* the message area. */
  328.         }
  329.  
  330.     /* Make sure that the physical and virtual displays agree. Unlike before,
  331.      * the "updateline" code is only called with a line that has been updated
  332.      * for sure.
  333.      */
  334.     Cconws("\033f");            /* invisible cursor    */
  335.     for (i = 0; i < term.t_nrow; ++i)
  336.         {
  337.         vp1 = vscreen[i];
  338.  
  339.         if ((vp1->v_flag&VFCHG) != 0)
  340.             {
  341.             vp1->v_flag &= ~VFCHG;
  342.             vp2 = pscreen[i];
  343.             updateline(i, &vp1->v_text[0], &vp2->v_text[0]);
  344.             }
  345.         }
  346.  
  347.     /* Finally, update the hardware cursor and flush out buffers. */
  348.     Cconws("\033e");            /* make cursor visible */
  349.     movecursor(currow, curcol);
  350. /*    (*term.t_flush)();    */
  351. }
  352.  
  353. /*
  354.  * Update a single line. This does not know how to use insert or delete
  355.  * character sequences; we are using VT52 functionality. Update the physical
  356.  * row and column variables. It does try an exploit erase to end of line. The
  357.  * RAINBOW version of this routine uses fast video.
  358.  */
  359. updateline(row, vline, pline)
  360.     char vline[];
  361.     char pline[];
  362. {
  363.     register char *cp1;
  364.     register char *cp2;
  365.     register char *cp3;
  366.     register char *cp4;
  367.     register char *cp5;
  368.     register int nbflag;
  369.     int         temp;
  370.  
  371.     if (vscreen[row]->v_flag & MDLIN) {
  372.     Cconws("\033p");
  373.     }
  374.     cp1 = &vline[0];                    /* Compute left match.  */
  375.     cp2 = &pline[0];
  376.  
  377.     while (cp1!=&vline[term.t_ncol] && cp1[0]==cp2[0])
  378.         {
  379.         ++cp1;
  380.         ++cp2;
  381.         }
  382.  
  383.     /* This can still happen, even though we only call this routine on changed
  384.      * lines. A hard update is always done when a line splits, a massive
  385.      * change is done, or a buffer is displayed twice. This optimizes out most
  386.      * of the excess updating. A lot of computes are used, but these tend to
  387.      * be hard operations that do a lot of update, so I don't really care.
  388.      */
  389.     if (cp1 == &vline[term.t_ncol])             /* All equal. */
  390.         return;
  391.  
  392.     nbflag = FALSE;
  393.     cp3 = &vline[term.t_ncol];          /* Compute right match. */
  394.     cp4 = &pline[term.t_ncol];
  395.  
  396.     while (cp3[-1] == cp4[-1])
  397.         {
  398.         --cp3;
  399.         --cp4;
  400.         if (cp3[0] != ' ')              /* Note if any nonblank */
  401.             nbflag = TRUE;              /* in right match. */
  402.         }
  403.  
  404.     cp5 = cp3;
  405.  
  406.     if (nbflag == FALSE)                /* Erase to EOL ? */
  407.         {
  408.         while (cp5!=cp1 && cp5[-1]==' ')
  409.             --cp5;
  410.         if ((int)(cp3-cp5) <= 3)                 /* Use only if erase is */
  411.             cp5 = cp3;                  /* fewer characters. */
  412.         }
  413.  
  414.     movecursor(row, (int)(cp1-&vline[0]));       /* Go to start of line. */
  415.     while (cp1 != cp5)                  /* Ordinary. */
  416.         {
  417.     Cconout(*cp1);            /* (*term.t_putchar)(*cp1);    */
  418.         ++ttcol;
  419.         *cp2++ = *cp1++;
  420.         }
  421.  
  422.     if (cp5 != cp3)                     /* Erase. */
  423.         {
  424.     Cconws("\033K");        /* (*term.t_eeol)();    */
  425.         while (cp1 != cp3)
  426.             *cp2++ = *cp1++;
  427.         }
  428.     if (vscreen[row]->v_flag & MDLIN){
  429.     Cconws("\033q");
  430.     }
  431. }
  432.  
  433. /* -eof- */
  434.